#pragma once

#include <string>
#include <list>
#include <map>
#include <boost/cstdint.hpp>
#include <boost/mpl/vector/vector10.hpp>
#include <alpha/utility/datatype.hpp>
#include <alpha/utility/simple_map.hpp>

namespace alpha { namespace rpc {

template <template <typename> class Tmpl>
struct basic_bencode: alpha::utility::datatype<basic_bencode<Tmpl>, Tmpl>
{
	basic_bencode() {}
	
	template <typename T>
	basic_bencode(T const & v): alpha::utility::datatype<basic_bencode<Tmpl>, Tmpl>(v) {}

	template <typename T>
	basic_bencode & operator =(T const& v)
	{
		this->assign(v);
		return *this;
	}
};

namespace detail {
	
	template <typename T>
	struct bencode_tmpl
	{
		typedef boost::intmax_t integer;
		typedef std::string string;
		typedef std::list<T> list;
		typedef alpha::utility::simple_map<string, T> dictionary;
		typedef boost::mpl::vector4<dictionary, integer, string, list> type;
	};
	
} // namespace detail

typedef basic_bencode<detail::bencode_tmpl> bencode;

}} // namespace alpha::rpc
